package com.example.learnvien.assets;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;

import com.example.learnvien.LearnViEnApplication;
import com.example.learnvien.data.LetterItemData;
import com.example.learnvien.data.NumberItemData;

public final class Assets
{
	private static final String EN_FILE = "en";
	private static final String VI_FILE = "vi";
	private static final String EN_PATH = "en/";
	private static final String VI_PATH = "vi/";

	public static boolean sIsVi = true;

	public static void init()
	{
		Image.init();
		Sound.init();
		Xml.init();
	}

	public static InputStream getInputStream(String fileName)
	{
		try
		{
			return LearnViEnApplication.getInstance().getAssets().open(fileName);
		} catch (IOException e)
		{
			e.printStackTrace();
		}
		return null;
	}

	public static final class Xml
	{
		private static final String PATH_XML = "xml/";

		// We don't use namespaces
		private static final String ns = null;
		private static XmlPullParser sParser;

		public static void init()
		{
			sParser = android.util.Xml.newPullParser();
			try
			{
				sParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,
						false);
			} catch (XmlPullParserException e)
			{
				e.printStackTrace();
			}

			Text.init();
			LetterItem.init();
			NumberItem.init();
		}

		public static final class Text
		{
			// Text id
			public static final String LANGUAGE_VI = "language_vi";
			public static final String LANGUAGE_EN = "language_en";
			public static final String WORD = "word";
			public static final String LETTER = "letter";

			// Private constants
			private static final String PATH_TEXT = PATH_XML + "text/";

			private static final String TAG_RESOURCE = "resource";
			private static final String TAG_STRING = "string";

			private static final String ATTRIBUTE_STRING_ID = "id";

			private static Map<String, String> sCommonVi = new HashMap<String, String>();
			private static Map<String, String> sCommonEn = new HashMap<String, String>();

			private static void loadCommonText(boolean isVi)
			{
				InputStream inputStream = getInputStream(PATH_TEXT
						+ (isVi ? VI_FILE : EN_FILE));

				try
				{
					sParser.setInput(inputStream, null); // if vi_file true else
					sParser.nextTag();
					readTexts(sParser, isVi);
				} catch (Exception e)
				{
					e.printStackTrace();
				}

				try
				{
					inputStream.close();
				} catch (IOException e)
				{
					e.printStackTrace();
				}
			}

			private static void readTexts(XmlPullParser parser, boolean isVi)
					throws XmlPullParserException, IOException
			{
				Map<String, String> strings = isVi ? sCommonVi : sCommonEn;

				parser.require(XmlPullParser.START_TAG, ns, TAG_RESOURCE);
				while (parser.next() != XmlPullParser.END_TAG)
				{
					if (parser.getEventType() != XmlPullParser.START_TAG)
					{
						continue;
					}
					String name = parser.getName().trim();
					if (name.equalsIgnoreCase(TAG_STRING))
					{
						String id = parser.getAttributeValue(ns,
								ATTRIBUTE_STRING_ID);
						if (parser.next() == XmlPullParser.TEXT)
						{
							String value = parser.getText();
							strings.put(id, value);

							parser.next();
						}
					} else
					{
						skip(parser);
					}
				}
			}

			public static String getCommonText(String idString)
			{
				if (idString == null || TextUtils.isEmpty(idString.trim()))
				{
					return "";
				}

				idString = idString.trim().toLowerCase(Locale.getDefault());
				try
				{
					return sIsVi ? sCommonVi.get(idString)	: sCommonEn.get(idString);
				}
				catch (IndexOutOfBoundsException e)
				{
					e.printStackTrace();
				}
				return "";
			}

			public static void init()
			{
				loadCommonText(true);
				loadCommonText(false);
			}
		}

		public static final class LetterItem
		{
			private static final String PATH_BUTTON_ITEM = PATH_XML
					+ "letter_item/";

			private static final String TAG_ITEMS = "items";
			private static final String TAG_LETTER = "letter";

			private static final String ATTRIBUTE_LETTER_ID = "id";
			private static final String ATTRIBUTE_LETTER_NAME = "name";
			private static final String ATTRIBUTE_LETTER_SOUND = "sound";
			private static final String ATTRIBUTE_LETTER_ICON = "icon";
			private static final String ATTRIBUTE_LETTER_PHRASE = "phrase";
			private static final String ATTRIBUTE_LETTER_SOUND_PHRASE = "sound_phrase";

			private static List<LetterItemData> sItemDatasVi = new ArrayList<LetterItemData>();
			private static List<LetterItemData> sItemDatasEn = new ArrayList<LetterItemData>();

			public static void init()
			{
				loadLetterItem(true);
				loadLetterItem(false);
			}

			private static void loadLetterItem(boolean isVi)
			{
				InputStream inputStream = getInputStream(PATH_BUTTON_ITEM
						+ (isVi ? VI_FILE : EN_FILE));

				try
				{
					sParser.setInput(inputStream, null); // if vi_file true else
					sParser.nextTag();
					readLetters(sParser, isVi);
				} catch (Exception e)
				{
					e.printStackTrace();
				}

				try
				{
					inputStream.close();
				} catch (IOException e)
				{
					e.printStackTrace();
				}
			}

			public static List<LetterItemData> getItems()
			{
				return sIsVi ? sItemDatasVi : sItemDatasEn;
			}

			public static List<LetterItemData> getItems(boolean isVi)
			{
				return isVi ? sItemDatasVi : sItemDatasEn;
			}

			private static void readLetters(XmlPullParser parser, boolean isVi)
					throws XmlPullParserException, IOException
			{
				List<LetterItemData> itemDatas = isVi ? sItemDatasVi
						: sItemDatasEn;
				parser.require(XmlPullParser.START_TAG, ns, TAG_ITEMS);
				while (parser.next() != XmlPullParser.END_TAG)
				{
					if (parser.getEventType() != XmlPullParser.START_TAG)
					{
						continue;
					}
					String name = parser.getName().trim();
					if (name.equalsIgnoreCase(TAG_LETTER))
					{
						LetterItemData itemData = new LetterItemData();

						itemData.mId = parser.getAttributeValue(ns,
								ATTRIBUTE_LETTER_ID);

						String pathIcon = parser.getAttributeValue(ns,
								ATTRIBUTE_LETTER_ICON);
						itemData.mImageIcon = Image.getDrawable(Image.PATH_LETTER_ICONS
								+ (isVi ? VI_PATH : EN_PATH) + pathIcon);

						itemData.mLetter = parser.getAttributeValue(ns,
								ATTRIBUTE_LETTER_NAME);
						itemData.mPhrase = parser.getAttributeValue(ns,
								ATTRIBUTE_LETTER_PHRASE);

						itemData.mSound = Sound.PATH_SOUND_LETTER
								+ (isVi ? VI_PATH : EN_PATH)
								+ parser.getAttributeValue(ns,
										ATTRIBUTE_LETTER_SOUND);
						itemData.mSoundPhrase = Sound.PATH_SOUND_PHRASE
								+ (isVi ? VI_PATH : EN_PATH)
								+ parser.getAttributeValue(ns,
										ATTRIBUTE_LETTER_SOUND_PHRASE);

						itemDatas.add(itemData);

						parser.next();
					} else
					{
						skip(parser);
					}
				}
			}
		}

		public static final class NumberItem
		{
			private static final String PATH_NUMBER_ITEM = PATH_XML
					+ "number_item";

			private static final String TAG_ITEMS = "items";
			private static final String TAG_NUMBER = "number";

			private static final String ATTRIBUTE_NUMBER_ID = "id";
			private static final String ATTRIBUTE_NUMBER_SOUND = "sound";
			private static final String ATTRIBUTE_NUMBER_ICON = "icon";

			private static List<NumberItemData> sItemDatas = new ArrayList<NumberItemData>();

			public static void init()
			{
				loadNumberItem();
			}

			private static void loadNumberItem()
			{
				InputStream inputStream = getInputStream(PATH_NUMBER_ITEM);

				try
				{
					sParser.setInput(inputStream, null); // if vi_file true else
					sParser.nextTag();
					readLetters(sParser);
				} catch (Exception e)
				{
					e.printStackTrace();
				}

				try
				{
					inputStream.close();
				} catch (IOException e)
				{
					e.printStackTrace();
				}
			}

			public static List<NumberItemData> getItems()
			{
				return sItemDatas;
			}

			private static void readLetters(XmlPullParser parser)
					throws XmlPullParserException, IOException
			{
				parser.require(XmlPullParser.START_TAG, ns, TAG_ITEMS);
				while (parser.next() != XmlPullParser.END_TAG)
				{
					if (parser.getEventType() != XmlPullParser.START_TAG)
					{
						continue;
					}
					String name = parser.getName().trim();
					if (name.equalsIgnoreCase(TAG_NUMBER))
					{
						NumberItemData itemData = new NumberItemData();

						itemData.mId = parser.getAttributeValue(ns,
								ATTRIBUTE_NUMBER_ID);

						String pathIcon = parser.getAttributeValue(ns,
								ATTRIBUTE_NUMBER_ICON);
						itemData.mImageIcon = Image.getDrawable(Image.PATH_NUMBER_ICONS
								+ pathIcon);

						String pathSound = parser.getAttributeValue(ns,
								ATTRIBUTE_NUMBER_SOUND);
						itemData.mSoundVi = Sound.PATH_SOUND_NUMBER + VI_PATH
								+ pathSound;
						itemData.mSoundEn = Sound.PATH_SOUND_NUMBER + EN_PATH
								+ pathSound;

						sItemDatas.add(itemData);

						parser.next();
					} else
					{
						skip(parser);
					}
				}
			}
		}

		private static void skip(XmlPullParser parser)
				throws IllegalStateException, XmlPullParserException,
				IOException
		{
			if (parser.getEventType() != XmlPullParser.START_TAG)
			{
				throw new IllegalStateException();
			}
			int depth = 1;
			while (depth != 0)
			{
				switch (parser.next())
				{
				case XmlPullParser.END_TAG:
					depth--;
					break;
				case XmlPullParser.START_TAG:
					depth++;
					break;
				}
			}
		}
	}

	/**
	 * For processing Asset Images
	 */
	public static final class Image
	{
		public static final String PATH_IMAGE = "image/";
		public static final String PATH_LETTER_ICONS = PATH_IMAGE
				+ "letter_icons/";
		public static final String PATH_NUMBER_ICONS = PATH_IMAGE
				+ "number_icons/";

		/**
		 * Get {@link Drawable} for images
		 * 
		 * @param fileName
		 * @return {@link Drawable}
		 */
		public static Drawable getDrawable(String fileName)
		{
			Bitmap bitmap = BitmapFactory.decodeStream(getInputStream(fileName));
			return new BitmapDrawable(
					LearnViEnApplication.getInstance().getResources(), bitmap);
		}

		public static void init()
		{
		}
	}

	public static final class Sound
	{
		public static final String PATH_SOUND = "sound/";
		public static final String PATH_SOUND_LETTER = PATH_SOUND + "letter/";
		public static final String PATH_SOUND_NUMBER = PATH_SOUND + "number/";
		public static final String PATH_SOUND_PHRASE = PATH_SOUND + "phrase/";

		/**
		 * Get File Descriptor for sound
		 * 
		 * @param fileName
		 * @return {@link AssetFileDescriptor}
		 */
		public static AssetFileDescriptor getAssetFileDescriptor(String fileName)
		{
			try
			{
				return LearnViEnApplication.getInstance().getAssets().openFd(
						fileName);
			} catch (IOException e)
			{
				e.printStackTrace();
				return null;
			}
		}

		public static void init()
		{
		}
	}
}
